package com.acheli.rideable.entites;

import com.acheli.ACHeli;
import com.acheli.registry.network.ACHeliPacketType;
import com.acheli.registry.network.ICustomSyncable;
import com.acheli.rideable.factory.ACHeliEntitiesFactory;
import com.acheli.rideable.factory.SafetyFactoryProvider;
import com.acheli.rideable.functionLathes.ComponentFL;
import com.acheli.rideable.factory.ComponentFactory;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.AABB;
import org.jetbrains.annotations.NotNull;
import org.joml.Quaternionf;
import software.bernie.geckolib.core.animatable.GeoAnimatable;
import software.bernie.geckolib.core.animatable.instance.AnimatableInstanceCache;
import software.bernie.geckolib.core.animation.AnimatableManager;
import software.bernie.geckolib.util.GeckoLibUtil;

public class ComponentEntity extends Entity implements ICustomSyncable, GeoAnimatable {
    private ComponentFL componentFL;
    Quaternionf totalRotation = new Quaternionf();

    public ACHeliEntitiesFactory<ComponentEntity, ComponentFL> factory;
    private static final EntityDataAccessor<String> ID = SynchedEntityData.defineId(ComponentEntity.class, EntityDataSerializers.STRING);
    public final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);

    public boolean isEmpty = false;
    public ComponentEntity(EntityType<?> pEntityType, Level pLevel, RideableEntity rideableEntity, ComponentFL lathe) {
        super(pEntityType, pLevel);
        if (rideableEntity != null && lathe != null) {
            setUp(rideableEntity, lathe);
        } else {
            isEmpty = true;
        }

    }

    public void setUp(RideableEntity r, ComponentFL lathe) {
        this.factory = new ComponentFactory(this, r, lathe);
        factory.getProductFunction().INIT();
        this.setComponentFL(lathe);
        lathe.setBody(this);
    }

    public boolean doFactory(SafetyFactoryProvider<ACHeliEntitiesFactory<ComponentEntity, ComponentFL>> factoryProvider) {
        boolean notNull = factory != null;
        if (notNull) {
            factoryProvider.getFct(factory);
        }
        return notNull;
    }

    public String getID() {
        return this.entityData.get(ID);
    }

    public void setID(String ID) {
        this.entityData.set(ComponentEntity.ID, ID);
    }


    public void setComponentFL(ComponentFL componentFL) {
        this.componentFL = componentFL;
    }
    public ComponentFL getComponentFL( ) {
        return componentFL;
    }


    @Override
    public void tick() {
        super.tick();
        if (componentFL != null) {
            componentFL.tick();
            componentFL.bodyTick(this);
        }
        if (factory == null) {
            ACHeli.LOGGER.info("factory is Null");
        }

    }

//    public void renderTick(PoseStack matrices, float tickDelta) {
//        if (componentFL != null) {
//            componentFL.renderTick(this, matrices, tickDelta);
//        }
//    }

    @Override
    public boolean onGround() {
        boolean onG = super.onGround();
        if (factory != null) {
            factory.getProductFunction().getFL().onGround(onG);
        }
        return onG;
    }

    @Override
    public boolean canRiderInteract() {
        return true;
    }

    @Override
    public boolean canBeHitByProjectile() {
        return true;
    }
    @Override
    public boolean isAttackable() {
        return true; // 允许实体被攻击/交互
    }

    @Override
    public boolean isPickable() {
        return true; // 允许实体被选中
    }
    @Override
    public @NotNull InteractionResult interact(Player pPlayer, InteractionHand pHand) {
        System.out.println(getID());
        if (factory != null) {
            factory.getProductFunction().interact(pPlayer, pHand);
        }
        return super.interact(pPlayer, pHand);
    }

    @Override
    public boolean shouldRenderAtSqrDistance(double distance) {
        if (! isEmpty && factory != null) {
            factory.getProductFunction().renderDistance(distance);
        }
        return super.shouldRenderAtSqrDistance(distance);
    }

    public boolean shouldRender() {
        if (! isEmpty && factory != null) {
            return  factory.getProductFunction().shouldRender();
        }
        return true;
    }

    @Override
    protected AABB makeBoundingBox() {
        if (getComponentFL() != null) {
            return getComponentFL().getVisibilityBoundingAABB(super.makeBoundingBox());
        }
        return super.makeBoundingBox();
    }

    @Override
    public AABB getBoundingBoxForCulling() {
        if (getComponentFL() != null) {
            return getComponentFL().getVisibilityBoundingAABB(super.getBoundingBoxForCulling());
        }
        return super.getBoundingBoxForCulling();
    }

    @Override
    protected void defineSynchedData() {
        this.entityData.define(ID,"empty");
    }

    @Override
    protected void readAdditionalSaveData(CompoundTag pCompound) {
        if (pCompound.contains("ID")) {
            this.entityData.set(ID,pCompound.getString("ID"));
        }
    }

    @Override
    protected void addAdditionalSaveData(CompoundTag pCompound) {
        pCompound.putString("ID", this.entityData.get(ID));
    }

    @Override
    public CompoundTag serverReceiveAndSending(CompoundTag serverOriginNbt, ServerPlayer executingPlayer, ACHeliPacketType packetType) {
        if (factory != null) {
            if (packetType == ACHeliPacketType.ComponentEvent || packetType == ACHeliPacketType.ComponentActive) {
                factory.getProductFunction().getFL().serverReceiveAndSending(serverOriginNbt, executingPlayer, packetType);
            }
            return factory.getProductFunction().serverReceiveAndSending(serverOriginNbt, executingPlayer, packetType);
        }
        return null;
    }

    @Override
    public void clientReceive(CompoundTag receivedNbt, boolean fromSelf, ACHeliPacketType packetType) {
        if (factory != null) {
            factory.getProductFunction().clientReceive(receivedNbt, fromSelf, packetType);
        }
    }
    public void setRotation(Quaternionf totalRotation) {
        this.totalRotation = totalRotation;
    }

    public Quaternionf getRotation() {
        return totalRotation;
    }
    public void applyRotation(PoseStack matrices) {
        matrices.mulPose(this.totalRotation);
    }

    @Override
    public void registerControllers(AnimatableManager.ControllerRegistrar controllers) {

    }

    @Override
    public AnimatableInstanceCache getAnimatableInstanceCache() {
        return geoCache;
    }

    @Override
    public double getTick(Object object) {
        return 0;
    }


}